<template>
  <div class="box_1">
    <div class="head"> <van-icon name="arrow-left" class="leftbtn" @click="back" />
      <span @click="back">返回</span>拼图小游戏</div>
    <div class="game">
      <div class="left">
        <div>随机图片：<span>图{{imgNum+1}}</span></div>
        <div>图片星级：<van-rate v-model="value" readonly /></div>
        <div><img :src="imgUrl" class="imgView"></div>
        <div>选择难度系数：<input v-model="difficulty" type="number" class="input" min="3" disabled='true' max="9" style="text-align: center"></div>
        <div class="btns">
          <button @click="imgChange()">换一张图</button>
          <button @click="startGame()" :disabled="restart ? !restart : !restart" v-html="restart ? '开始游戏' : '加油啊!'"></button>
          <button @click="suspend()" :disabled="!restart ? restart : restart" v-html="timers ? '暂停' : '继续'"></button>
          <button @click="again()" :disabled="!restart ? restart : restart">重新开始</button>
        </div>
      </div>
      <div class="right">
        <div class="message">
          <div><h2>已走<span>{{stepMsg }}</span>步</h2></div>
          <div><h2>{{gameMsg}}</h2></div>
          <div><h2>已用时<span>{{timeMsg }}</span>秒</h2></div>
        </div>
        <div class="suspend" :style="styles">已暂停</div>
        <div class="box">
          <div v-if="!gameOver" class="imgBox">
            <div
                v-for="(item,index) in imgFragment"
                :key="index"
                :style="{
                background:item.background,
                height:itemWidth+'px',
                width:itemWidth+'px',
                position:item.positon,
                left:item.left+'px',
                top:item.top+'px'
              }"
                :class="{active:item.isActive}"
                :id="item.id"
                @mousedown="handleMousedown"
                @contextmenu.stop.prevent="handleContextmenu"
            />
          </div>
          <div v-else class="msgBox">本次得分：{{ score }}</div>
        </div>
      </div>
    </div>
    <div class="tips">
      <p>得分计算（满分100）</p>
      <p>总分=星级*150+难度*300</p>
      <p>失分=步数*10+时间(秒)*5</p>
      <p>得分=(总分-失分)/总分*100</p>
    </div>
  </div>
</template>

<script>
export default {
  name: 'Puzzle',
  data() {
    return {
      styles:'',
      timers:false,//倒计时
      value: 1, // 图片星级
      score: 0,
      restart:true,
      needGameInit: true,
      timer: null,
      gameOver: false,
      itemWidth: 20,
      keys: [],
      orig_keys: [],
      imgFragment: [], // 拼图碎片
      item: [], // 拼图碎片 副本
      imgUrl: '', // 整张拼图
      imgNum: 1,
      difficulty: 3, // 难度系数 横纵分割
      timeMsg: 0,
      stepMsg: 0,
      gameMsg: '准备好了么？',
      gameMsgArr: [
        '继续加油！',
        '保持冷静！',
        '马上就要完成了！',
        '快成功了！',
        '还差一点儿！',
        '加油啊',
        '继续保持',
        '加油加油！',
        '吁。。。',
        '别急，慢慢来',
        '坚持就是胜利',
        '稳住！',
        '再好好看看',
        '快了快了'
      ],
      imgList: [// 拼图图库 star 标识难度 用于分值计算权重
        { url: require('../assets/1.jpg'), star: '4' },
        { url: require('../assets/2.jpg'), star: '9' },
        { url: require('../assets/3.jpg'), star: '3' },
        { url: require('../assets/4.jpg'), star: '6' },
        { url: require('../assets/5.jpg'), star: '8' },
        { url: require('../assets/6.jpg'), star: '7' },
        { url: require('../assets/7.jpg'), star: '5' },
      ]
    }
  },
  watch: {
    difficulty: function() {
      this.gameInit()
    },
    imgUrl: function() {
      this.gameInit()
    }
  },
  mounted() {
    // 页面初始化
    this.imgChange()
    this.gameInit()
  },
  methods: {
    back(){
      this.$router.back()
    },
    gameInit: function() {
      this.needGameInit = false
      this.gameOver = false
      this.imgFragment = []
      this.item = []
      this.keys = []
      this.orig_keys = []

      // 关闭计时器
      if (!this.timer) {
        this.timer = null
      } else {
        // 关闭计时器
        clearInterval(this.timer)
      }

      this.stepMsg = 0
      this.gameMsg = '准备好了么？'
      this.timeMsg = 0

      const len = this.difficulty * this.difficulty
      this.itemWidth = 200/ this.difficulty

      for (var i = 0; i < len; i++) {
        var background = `url(${this.imgUrl}) no-repeat -${(i % this.difficulty) * this.itemWidth}px -${Math.floor((i) / this.difficulty) * this.itemWidth}px`
        this.keys.push(i)
        this.orig_keys.push(i)
        this.item.push({ 'background': background, 'positon': 'static', 'left': '', 'top': '', 'isActive': false, 'moveFlag': false })
        this.imgFragment.push({ 'background': background, 'positon': 'static', 'left': '', 'top': '', 'isActive': false, 'moveFlag': false })
      }
    },

    start: function() {
      this.imgFragment = []
      // 随机位置 依据随机数排序
      // 随机位置
      this.keys.sort(function(a, b) {
        console.log(a,b)
        return Math.random() > 0.5 ? 1 : -1
      })

      var keys = this.keys
      var colNum = 0
      var rowNum = 0

      for (var i = 0; i < keys.length; i++) {
        if (i > 0) {
          if (i % this.difficulty === 0) {
            rowNum++
            colNum = 0
          }
        }

        var item = this.item[keys[i]]
        item.positon = 'absolute'
        item.left = colNum++ * this.itemWidth
        item.top = rowNum * this.itemWidth
        item.pos = i
        item.id = i
        item.key = keys[i]
        item.moveFlag = false
        item.isActive = false
        this.imgFragment.push(item)
      }
    },

    // 寻找已经选择的目标
    findTarget: function(current) {
      // this.imgFragment 数组元素为对象
      for (var i = 0; i < this.imgFragment.length; i++) {
        // findTarget 仅比较值就行，因为 current 是字符串，i 是数字。
        if (current != i && this.imgFragment[i].moveFlag) {
          return this.imgFragment[i]
        }
      }

      // this.imgFragment.find((item, index) => {
      //   return current != index && item.moveFlag //始终返回 undefined
      // })
    },

    // 交换两个div位置
    exchange: function(from, target) {
      var from_left = from.left
      var from_top = from.top
      var from_pos = from.pos
      var from_key = from.key

      var target_left = target.left
      var target_top = target.top
      var target_pos = target.pos
      var target_key = target.key

      from.left = target_left
      from.top = target_top

      from.pos = target_pos

      target.left = from_left
      target.top = from_top

      target.isActive = false
      target.pos = from_pos
      target.moveFlag = false

      // 交换它们在this.keys中的位置
      this.keys.splice(from_pos, 1, target_key)
      this.keys.splice(target_pos, 1, from_key)

      // 如果相等表示已经找好了
      if (this.diff(this.orig_keys, this.keys)) {
        // 关闭计时器
        clearInterval(this.timer)
        this.gameMsg = '太棒了，成功了！'

        this.tips()
        this.scoreCount()

        this.needGameInit = true
      } else {
        // 提示未完成，继续加油
        // 随机数在范围从0到小于1，也就是说，从0（包括0）往上，但是不包括1（排除1）
        var max = this.gameMsgArr.length
        var i = Math.floor(Math.random() * max)
        this.gameMsg = this.gameMsgArr[i]
      }
    },

    // 计算得分
    scoreCount: function() {
      // 满分100
      // 总分=星级*150+难度*300
      var total = Number(this.star * 150) + Number(this.difficulty * 300)
      // 失分=步数*10+时间（秒）*5
      var lost = Number(this.stepMsg * 10) + Number(this.timeMsg / 1000 * 5)
      // 得分=(总分-失分)/总分*100
      this.score = Math.round((total - lost) / total * 100)
      if (this.score < 0) { this.score = 0 }
      this.restart = true
    },

    // 完成后倒计时的提示
    tips: function() {
      setTimeout(() => {
        this.gameOver = true
      }, 1000)
    },

    // 比较两个数组，如果一模一样 证明顺序对了
    diff: function(a, b) {
      var me = this
      var isArrayA = Array.isArray(a)
      var isArrayB = Array.isArray(b)
      if (isArrayA && isArrayB) { // 如果都是数组
        if (a.length === b.length) { // 如果长度相等
          return a.every(function(e, i) { // 用every和递归来比对a数组和b数组的每个元素，并返回
            return me.diff(e, b[i])
          })
        }
        // 长度都不等直接返回false
        return false
      } else {
        return String(a) === String(b)
      }
    },

    // 设置拖动 onmousedown
    handleMousedown: function(e) {
      var current = e.srcElement.id
      var target = this.findTarget(current)// 拼图碎片
      if (e.button === 0) { // 左键
        // this VueComponent
        if (target) {
          this.exchange(this.imgFragment[current], target)
          this.stepMsg++
        } else {
          this.imgFragment[current].isActive = true
          this.imgFragment[current].moveFlag = true
        }
      }
    },
    // 右键取消
    handleContextmenu: function(e) {
      console.log(e)
      var target = this.findTarget()
      if (target) {
        target.isActive = false
        target.moveFlag = false
      }
    },

    // 开始游戏
    startGame: function() {
      if (this.needGameInit) { this.gameInit() }
      this.start()
      this.timeStart()
      this.restart = false
      this.timers = true
    },

    timeStart: function() {
      // 关闭计时器
      if (!this.timer) {
        this.timer = null
      } else {
        // 关闭计时器
        clearInterval(this.timer)
      }

      this.timer = setInterval(() => {
        this.timeMsg++
      },1000)
    },
    // 随机的一张图
    imgChange: function() {
      // 随机的一张图
      var old = this.imgNum
      var max = this.imgList.length
      do {
        this.imgNum = Math.floor(Math.random() * max)
      } while (this.imgNum === old)
      this.imgUrl = this.imgList[this.imgNum].url
      this.star = this.imgList[this.imgNum].star
      this.value = this.imgList[this.imgNum].star - 2
      this.difficulty = this.imgList[this.imgNum].star
      this.restart = true
      this.timers = true
      this.styles = 'display: none'
    },
    //暂停继续
    suspend: function (){
      if(this.timers){
        clearInterval(this.timer)
        this.timers = false
        this.styles = 'display: block'
      }else {
        this.timers = true
        this.styles = 'display: none'
        this.timer = setInterval(() => {
          this.timeMsg++
        },1000)
      }
    },
    //重来
    again(){
      if(this.timers == false){
        this.timers = true
        this.styles = 'display: none'
      }
      clearInterval(this.timer)
      this.start()
      this.timeMsg = 0
      this.stepMsg = 0
      this.timer = setInterval(() => {
        this.timeMsg++
      },1000)
    }
  }
}
</script>

<style scoped lang="less">
.box_1 {
  padding-bottom: 1px;
}
/deep/.van-rate__icon{
  font-size: 12px;
}
body{
  font-size:16px;
}

h1{
  text-align: center;
}

div.game{
  width: 100%;
  padding: 0 10px;
  box-sizing: border-box;
  display: flex;
  flex-direction: row;
  //justify-content: center;
}
.head {
  font-size: 25px;
  text-align: center;
  position: relative;
  height: 40px;
  line-height: 40px;
  .leftbtn{
    width: 45px;
    height: 40px;
    margin-bottom: 5px;
    font-size: 24px;
    font-weight: bolder;
    text-align: center;
    line-height: 40px;
    position: absolute;
    left: -5px;
    top: 0px;
  }
  span {
    font-size: 18px;
    position: absolute;
    left: 25px;
    //top: -1px;
  }
}
div.left{
  width: 100px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 35px;
  background-color: #f7f7f7;
  margin-right:10px;
  //padding:10px;
  font-size: 12px;
}

div.star{
  display: inline-block;
  width:80px;
  height:14px;
  margin-bottom: -3px;
}

/* 预览图片 */
.imgView{
  width: 80px;
  box-sizing: content-box;
  border: 8px solid #bc6e42;
}

.input{
  -webkit-appearance: none;
  background-color: #fff;
  background-image: none;
  border-radius: 4px;
  border: 1px solid #dcdfe6;
  box-sizing: border-box;
  color: #606266;
  display: inline-block;
  font-size: inherit;
  height: 40px;
  line-height: 40px;
  outline: none;
  padding: 0 15px;
  transition: border-color .2s cubic-bezier(.645,.045,.355,1);
  width: 100px;
}

div.btns{
  width: 100%;
  padding:10px 0;
}

button{
  display: inline-block;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  background: #fff;
  border: 1px solid #dcdfe6;
  color: #606266;
  -webkit-appearance: none;
  text-align: center;
  box-sizing: border-box;
  outline: none;
  transition: .1s;
  font-weight: 500;
  padding: 12px 20px;
  font-size: 14px;
  border-radius: 4px;
  width:100px;
}

div.tips{
  margin: 20px auto;
  padding: 10px;
  width: 90%;
  box-sizing: border-box;
  border:1px dotted #999;
}

div.right{
  position: relative;
  width: calc(100% - 100px);
  background-color: #f7f7f7;
  padding:10px;
}
.suspend{
  position: absolute;
  bottom: 38px;
  width: 200px;
  height: 200px;
  background-color: rgba(0,0,0,0.3);
  z-index: 2;
  font-size: 20px;
  color: white;
  line-height: 200px;
  text-align: center;
}

.message{
  span {
    color: red;
    font-size: 35px;
    padding: 15px;
  }
}

/* 拼图盒子 */
.box{
  margin-top: 50px;
  width: 200px;
  height: 200px;
  box-sizing: content-box;
  position: relative;
}

.imgBox div{
  box-sizing: border-box;
  border: 1px dotted #fff;
  float:left;
  cursor:move;
}

/* 消息盒子 */
.box .msgBox{
  box-sizing: border-box;
  line-height:70px;
  text-align:center;
  font-size:25px;
  color:#F56200;
  margin:0;
}

.active{
  border:8px solid #bc6e42 !important;
}
</style>